package com.squirrel.common.util;

import com.squirrel.common.exception.BaseException;
import com.squirrel.common.response.code.CodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import org.bytedeco.javacv.Frame;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;


/**
 * @Description ImageToolUtils 图片工具类
 * @Author 关远键
 * @Version v1.0.0
 * @Date 2021/11/25 21:06
 */
@Slf4j
public class ImageToolUtils {

    //截取图片第几帧
    private static final int INDEX = 150;

    /**
     * 图片名称
     * @author 关远键
     * @date 2021/11/25 21:48
     * @param videoPath 视频路径
     * @return java.lang.String
     */
    public static String randomGrabberFFmpegVideoImage(String videoPath){
        String targetFilePath = null;
        String picPath = videoPath.substring(0, videoPath.lastIndexOf("\\"));
        String videoName = videoPath.substring(videoPath.lastIndexOf('\\') + 1, videoPath.lastIndexOf('.'));

        log.info("视频路径：{}", videoPath);
        log.info("图片存放路径：{}", picPath);
        log.info("视频文件名：{}", videoName);


        try {
            FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(videoPath);
//            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoPath);
            ff.start();

            //判断是否是竖屏小视频
            String rotate = ff.getVideoMetadata("rotate");
            int ffLength = ff.getLengthInFrames();

            Frame f = null;
            int i = 0;
            while (i < ffLength) {
                f = ff.grabImage();
                if (INDEX == i) {
                    if (null != rotate && rotate.length() > 1) {
                        targetFilePath = doExecuteFrame(f, videoName + ".png", picPath, true);   //获取缩略图
                    } else {
                        targetFilePath = doExecuteFrame(f, videoName + ".png", picPath, false);   //获取缩略图
                    }
                    break;
                }
                i++;
            }

            ff.stop();
        } catch (Exception e) {
            log.error("获取帧数出错了");
            e.printStackTrace();
            throw new BaseException(CodeEnum.FAIL);
        }

        log.info("图片文件名：{}", targetFilePath);

        return targetFilePath;
    }

    /**
     * 保存图片
     * @author 关远键
     * @date 2021/11/25 21:49
     * @param f 窗体
     * @param picPath 保存路径
     * @param bool 是否旋转
     * @return java.lang.String 图片名称
     */
    public static String doExecuteFrame(Frame f, String picName, String picPath, boolean bool) throws Exception {
        if (null == f || null == f.image) {
            return null;
        }

        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bi = converter.getBufferedImage(f);

        if (bool) {
            Image image = (Image) bi;
            bi = rotate(image, 90);     //旋转90度
        }

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(bi, "png", os);
//        byte[] sdf = os.toByteArray();
        InputStream input = new ByteArrayInputStream(os.toByteArray());
        MultipartFile multipartFile = new MockMultipartFile(picName, picName, picName, input);

        try {
            multipartFile.transferTo(new File(picPath, picName));
            log.info("图片保存成功：{}", multipartFile.getOriginalFilename());
        } catch (IOException e) {
            log.error("保存图片出错了");
            throw new BaseException(CodeEnum.FAIL);
        }

        return multipartFile.getOriginalFilename();
    }

    /**
     * 图片旋转角度
     *
     * @param src   源图片
     * @param angel 角度
     * @return 目标图片
     */
    public static BufferedImage rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // calculate the new image size
        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);

        BufferedImage res = null;
        res = new BufferedImage(rect_des.width, rect_des.height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = res.createGraphics();
        // transform(这里先平移、再旋转比较方便处理；绘图时会采用这些变化，绘图默认从画布的左上顶点开始绘画，源图片的左上顶点与画布左上顶点对齐，然后开始绘画，修改坐标原点后，绘画对应的画布起始点改变，起到平移的效果；然后旋转图片即可)

        //平移（原理修改坐标系原点，绘图起点变了，起到了平移的效果，如果作用于旋转，则为旋转中心点）
        g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);


        //旋转（原理transalte(dx,dy)->rotate(radians)->transalte(-dx,-dy);修改坐标系原点后，旋转90度，然后再还原坐标系原点为(0,0),但是整个坐标系已经旋转了相应的度数 ）
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

//        //先旋转（以目标区域中心点为旋转中心点，源图片左上顶点对准目标区域中心点，然后旋转）
//        g2.translate(rect_des.width/2,rect_des.height/ 2);
//        g2.rotate(Math.toRadians(angel));
//        //再平移（原点恢复到源图的左上顶点处（现在的右上顶点处），否则只能画出1/4）
//        g2.translate(-src_width/2,-src_height/2);


        g2.drawImage(src, null, null);
        return res;
    }

    /**
     * 计算转换后目标矩形的宽高
     *
     * @param src   源矩形
     * @param angel 角度
     * @return 目标矩形
     */
    private static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        double cos = Math.abs(Math.cos(Math.toRadians(angel)));
        double sin = Math.abs(Math.sin(Math.toRadians(angel)));
        int des_width = (int) (src.width * cos) + (int) (src.height * sin);
        int des_height = (int) (src.height * cos) + (int) (src.width * sin);
        return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }

    /**
     * 保存用户头像
     * @author 关远键
     * @date 2021/11/26 11:09
     * @param nickname 用户昵称
     * @param avatarFile 头像文件
     * @param destPath 保存路径
     * @return java.lang.String
     */
    public static String saveAvatar(String nickname, MultipartFile avatarFile, String destPath) {
        File file = new File(destPath);
        //判断不存在该目录就创建
        if (!file.exists()) {
            if (!file.mkdirs()) {
                log.error("创建用户【{}】头像目录失败", nickname);
                throw new BaseException(CodeEnum.FAIL);
            }
        }

        String filename = nickname + "-" + "avatar.png";
        log.info("file===={}", file);
        log.info("filename===={}", filename);
        log.info("avatarFile===={}", avatarFile);
        try {
            avatarFile.transferTo(new File(file, filename));
            return filename;
        } catch (IOException e) {
            log.error("保存用户【{}】头像失败", nickname);
            e.printStackTrace();
            throw new BaseException(CodeEnum.FAIL);
        }
    }
}
